﻿using System.Web.UI;

namespace HeroldIT.Dnn.Modules
{
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class HierarchyObject<T> : IHierarchyData
    {
        #region constants

        private static readonly string categoryType = typeof (HierarchyObject<>).Name;

        #endregion

        #region static methods

        /// <summary>
        /// Returns the contained object from the <see cref="HierarchyObject{T}"/>.
        /// </summary>
        /// <param name="obj">The <see cref="HierarchyObject{T}"/> containing the desired object.</param>
        /// <returns>The contained object from the <see cref="HierarchyObject{T}"/>.</returns>
        public static explicit operator T(HierarchyObject<T> obj)
        {
            return obj.Object;
        }

        /// <summary>
        /// Returns a new <see cref="HierarchyObject{T}"/> containing the <paramref name="obj"/>.
        /// </summary>
        /// <param name="obj">The object to add to the <see cref="HierarchyObject{T}"/>.</param>
        /// <returns>A new <see cref="HierarchyObject{T}"/> containing the <paramref name="obj"/>.</returns>
        public static implicit operator HierarchyObject<T>(T obj)
        {
            return new HierarchyObject<T>(obj);
        }

        #endregion

        #region properties

        /// <summary>
        /// Gets the object contained in this <see cref="HierarchyObject{T}"/>.
        /// </summary>
        public T Object { get; private set; }

        /// <summary>
        /// Gets the parent object of this <see cref="HierarchyObject{T}"/>.
        /// </summary>
        public HierarchyObject<T> Parent { get; private set; }

        /// <summary>
        /// Gets the children collection of this <see cref="HierarchyObject{T}"/>.
        /// </summary>
        internal HierarchyObjectCollection<T> Children { get; private set; }

        #endregion

        #region constructors

        /// <summary>
        /// Creates a new <see cref="HierarchyObject{T}"/> containing the given <paramref name="obj"/>.
        /// </summary>
        /// <param name="obj">The object to add to the new <see cref="HierarchyObject{T}"/>.</param>
        public HierarchyObject(T obj) : this(null, obj)
        {}

        /// <summary>
        /// Creates a new <see cref="HierarchyObject{T}"/> containing the given <paramref name="obj"/> and with the given <paramref name="parent"/>.
        /// </summary>
        /// <param name="parent">The parent of the new <see cref="HierarchyObject{T}"/>.</param>
        /// <param name="obj">The object to add to the new <see cref="HierarchyObject{T}"/>.</param>
        public HierarchyObject(HierarchyObject<T> parent, T obj)
        {
            this.Parent = parent;
            this.Object = obj;
            this.Children = new HierarchyObjectCollection<T>(this);
            if (null != this.Parent)
            {
                this.Parent.Children.Add(this);
            }
        }

        #endregion

        #region methods

        /// <summary>
        /// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
        /// </returns>
        public override string ToString()
        {
            return this.Object.ToString();
        }

        #endregion

        #region Implementation of IHierarchyData

        /// <summary>
        /// Gets an enumeration object that represents all the child nodes of the current hierarchical node.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Web.UI.IHierarchicalEnumerable"/> collection of child nodes of the current hierarchical node.
        /// </returns>
        public IHierarchicalEnumerable GetChildren()
        {
            return this.Children;
        }

        /// <summary>
        /// Gets an <see cref="T:System.Web.UI.IHierarchyData"/> object that represents the parent node of the current hierarchical node.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Web.UI.IHierarchyData"/> object that represents the parent node of the current hierarchical node.
        /// </returns>
        public IHierarchyData GetParent()
        {
            return this.Parent;
        }

        /// <summary>
        /// Indicates whether the hierarchical data node that the <see cref="T:System.Web.UI.IHierarchyData"/> object represents has any child nodes.
        /// </summary>
        /// <returns>
        /// true if the current node has child nodes; otherwise, false.
        /// </returns>
        public bool HasChildren
        {
            get { return this.Children.Count > 0; }
        }

        /// <summary>
        /// Gets the hierarchical path of the node.
        /// </summary>
        /// <returns>
        /// A <see cref="T:System.String"/> that identifies the hierarchical path relative to the current node.
        /// </returns>
        public string Path
        {
            get
            {
                if (null != this.Parent)
                {
                    return this.Parent.Path + ">" + this.Object;
                }
                return this.Object.ToString();
            }
        }

        /// <summary>
        /// Gets the hierarchical data node that the <see cref="T:System.Web.UI.IHierarchyData"/> object represents.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Object"/> hierarchical data node object.
        /// </returns>
        object IHierarchyData.Item
        {
            get { return this; }
        }

        /// <summary>
        /// Gets the name of the type of <see cref="T:System.Object"/> contained in the <see cref="P:System.Web.UI.IHierarchyData.Item"/> property.
        /// </summary>
        /// <returns>
        /// The name of the type of object that the <see cref="T:System.Web.UI.IHierarchyData"/> object represents.
        /// </returns>
        string IHierarchyData.Type
        {
            get { return categoryType; }
        }

        #endregion
    }
}
